﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Drawing;

namespace FingerSC
{
    /// <summary>
    /// 指纹仪类：用于管理指纹仪的交互
    /// 向上提供的接口功能：
    /// 1）指纹下发到指纹仪；
    /// 2）指纹识别结果；
    /// 3）指纹录入；
    /// 对下，是基于System.IO.Ports空间中的SerialPort处理相关通信
    /// 1）处理相关协议；
    /// 2）上传下达，将抽象功能转换为具体的IO操作序列。
    /// </summary>
    public class FingerSC
    {
        #region 成员变量声明
        private SerialPort FSCCom = new SerialPort();//指纹仪的接口，用于进行具体的输入输出操作
        //串口通信相关参数，大部分不需要改。
        //串口名称需要根据需要进行修改，可使用setconf进行修改
        private string strBaudRate = "115200";
        private string strDateBits = "8";
        private string strStopBits = "1";
        private string strParity = "无";
        private string strPortName = "";
        /// <summary>
        ///状态标记
        ///在工作情况下，主机需要与指纹仪进行多次交互，即主机命令发给指纹仪（规格书中上位机发给指纹仪芯片）
        ///状态变化包含两部分：
        ///WorkingMode：当前所进行的工作。
        ///State：当前工作进行的程度，大部分情况01表示输出和输入；对录入指纹需要多次通信，要特别定义
        ///0无事等待指纹仪消息；1中断指令；2查询指纹数；3采集图像；4注册指纹；5匹配指纹；6删除指纹；7模板传输。
        /// </summary>
        int WorkingMode = 0;//0无事等待指纹仪消息；1中断指令；2查询指纹数；3采集图像；4注册指纹；5匹配指纹；6删除指纹；7模板传输。
        int State = 0;//对大部分命令，0命令发出，等待指纹仪回复；1获得指纹仪回复，操作结束；特殊之处

        byte[] FingerPrtTmp1 = new byte[256];//用于存放从指纹仪获得的第一个模板指纹数据
        byte[] FingerPrtTmp2 = new byte[256];//用于存放从指纹仪获得的第二个模板指纹数据
        private string strFingerPrtTmp1;//第二次修改新增，用于存放第一个模板数据的字符串形式
        private string strFingerPrtTmp2;//第二次修改新增，用于存放第二个模板数据的字符串形式
        //由于在获取指纹模板、匹配指纹过程中都需要指纹ID和模板编号作为输入参数。
        //这两个参数在函数调用中有，但在事件处理中也要用到，因而在这里暂时存放。
        int FingerID1, FingerID2;
        int FingerModelID1;
        int FingerNum;
        //update by xxd 2018/12/15
        //采集图像用的成员变量，用于存储采集到的指纹图像数据
        int FingerHeight, FingerWidth;//指纹图像的宽和高
        int FingerPicSize;//指纹图像总体大小
        byte[] FingerPic;//暂时不new对象，因为大小未知。
        int PicPackNum;//记录当前传输的数据包编号
        bool isPicValid = false;//当前指纹图像数据是否有效，开始没有图像数据，都无效

        /// <summary>
        /// 设备GUID
        /// </summary>
        private byte[] btysGUID = new byte[12];
        /// <summary>
        /// 设备GUID
        /// </summary>
        public byte[] GUID
        {
            get { return btysGUID; }
            set { btysGUID = value; }
        }

        /// <summary>
        /// 设备GUID (字符串)
        /// </summary>
        public string StrGUID
        {
            get { return byteToHexStr(GUID); }
        }

        #endregion

        #region 事件声明
        /// <summary>
        /// 由于指纹仪与上位机是异步操作，需要通过事件告知其他代码（进程等）指纹仪的工作状态；
        /// 在指纹仪完成各种操作后，通过对应事件向调用者进行通报。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        //完成获取指纹数目操作后将触发Alarm事件
        public delegate void AlarmEventHandler(object sender, FingerEventArgs e);//声明关于事件的委托
        public event AlarmEventHandler Alarm;//声明事件
        public delegate void FingerPrtTmpEventHandler(object sender, object sender1, object sender2, EventArgs e);//第二次修改新增，新事件FingerPrtTmp，用于展示采集的数据包，by szy
        public event FingerPrtTmpEventHandler FingerPrtTmp;//声明事件

        /// <summary>
        /// 事件参数类声明
        /// </summary>
        /// <param name="ConName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        /// 
        public class FingerEventArgs : EventArgs
        {
            /// <summary>
            /// 描述事件状况的字符串，一般中文信息
            /// </summary>
            public readonly string strReturn;//描述事件状况的字符串，一般中文信息
            /// <summary>
            /// 对应的命令
            /// </summary>
            public readonly int WorkingModel;//对应的命令
            /// <summary>
            /// 命令执行进度
            /// </summary>
            public readonly int State;//命令执行进度
            /// <summary>
            /// 命令执行结果编码，如0正确结束，-1出现错误
            /// </summary>
            public readonly int ResID;//命令执行结果编码，如0正确结束，-1出现错误
            /// <summary>
            /// 该命令对应的值，用户一般从这里取值，如指纹ID、指纹数目等
            /// </summary>
            public readonly int Result;//该命令对应的值，用户一般从这里取值，如指纹ID、指纹数目等
            /// <summary>
            /// 指纹仪返回串中，有意义的字节串
            /// </summary>
            public readonly byte[] RetBytes;//指纹仪返回串中，有意义的字节串

            /// <summary>
            /// 指纹事件回调
            /// </summary>
            /// <param name="strReturn">描述事件状况的字符串，一般中文信息</param>
            /// <param name="WorkingModel">对应的命令</param>
            /// <param name="State">命令执行进度</param>
            /// <param name="ResID">命令执行结果编码，如0正确结束，-1出现错误</param>
            /// <param name="Result">该命令对应的值，用户一般从这里取值，如指纹ID、指纹数目等</param>
            /// <param name="RetBytes">指纹仪返回串中，有意义的字节串</param>
            public FingerEventArgs(string strReturn, int WorkingModel, int State, int ResID, int Result, byte[] RetBytes)
            {
                this.strReturn = strReturn;
                this.WorkingModel = WorkingModel;
                this.State = State;
                this.ResID = ResID;
                this.Result = Result;
                this.RetBytes = RetBytes;
            }
        }


        /// <summary>
        /// 指纹仪设备事件回调
        /// </summary>
        public event FingerDeviceCallbackDelegate FingerDeviceCallbackEvent;

        /// <summary>
        /// 指纹仪设备事件回调
        /// </summary>
        /// <param name="FingerDeviceCallbackValue"></param>
        private void FingerDeviceCallback(FingerDeviceCallbackValue FingerDeviceCallbackValue)
        {
            
            if (FingerDeviceCallbackEvent != null)
            {
                FingerDeviceCallbackEvent(this, FingerDeviceCallbackValue);
            }
        }
        #endregion

        #region 初始化、状态查询、设置查询修改等相关
        public int SetConf(string ConName, string value)//设置相关参数；但无法校验参数正确性
        {
            switch (ConName)//根据参数种类，分别进行设置
            {
                case "BaudRate":
                    strBaudRate = value;
                    break;
                case "DateBits":
                    strDateBits = value;
                    break;
                case "StopBits":
                    strStopBits = value;
                    break;
                case "Parity":
                    strParity = value;
                    break;
                case "Port":
                    strPortName = value;
                    break;
            }////根据参数种类，分别进行设置
            return 0;
        }
        public int initial()//初始化函数
        {
            FSCCom.PortName = strPortName;//串口端口号

            //设置各“串口设置”
            Int32 iBaudRate = Convert.ToInt32(strBaudRate);
            Int32 iDateBits = Convert.ToInt32(strDateBits);

            FSCCom.BaudRate = iBaudRate;       //波特率
            FSCCom.DataBits = iDateBits;       //数据位

            //DataReceived函数是消息处理函数，负责对串口接收的数据进行解析；
            //下一语句将串口的数据接收消息挂接到FSCCom的DataReceived函数进行处理；
            FSCCom.DataReceived += new SerialDataReceivedEventHandler(DataReceived);


            switch (strStopBits)            //停止位
            {
                case "1":
                    FSCCom.StopBits = StopBits.One;
                    break;
                case "1.5":
                    FSCCom.StopBits = StopBits.OnePointFive;
                    break;
                case "2":
                    FSCCom.StopBits = StopBits.Two;
                    break;
                default:
                    return -1;//参数不正确
            }//停止位
            switch (strParity)             //校验位
            {
                case "无":
                    FSCCom.Parity = Parity.None;
                    break;
                case "奇校验":
                    FSCCom.Parity = Parity.Odd;
                    break;
                case "偶校验":
                    FSCCom.Parity = Parity.Even;
                    break;
                default:
                    return -1;//参数不正确
            }//校验位

            try
            {
                if (FSCCom.IsOpen == true)//如果打开状态，则先关闭一下
                {
                    FSCCom.Close();
                }
                FSCCom.Open();     //打开串口
            }
            catch(Exception ex )
            {
                FingerDeviceCallback(new FingerDeviceCallbackValue
                {
                    CallbackType = Enum_FingerDeviceCallbackType.PortInitException,
                    FingerPrintID = -1,
                    MessgeaInfo = "串口初始化异常",
                    Para1 = ex,
                });
            }
            //工作状态初始化
            WorkingMode = 0;
            State = 0;
            GetDevID();//初始化完成主动获取指纹仪guid
            return 0;
        }

        public int GetPort(ref string[] ports)
        {
            ports = SerialPort.GetPortNames();
            return 1;
        }

        public int ClosePort()//第一次修改新增 用于关闭串口 by szy
        {
            FSCCom.Close();
            return 0;
        }

        public bool IsOpen()//第一次修改新增 用于判断接口是否打开 by szy
        {
            if (FSCCom.IsOpen)
                return true;
            else return false;
        }

        public bool IsPicValid()//当前指纹图像数据是否有效
        {
            return isPicValid;
        }

        public byte[] GetFingerPic()//返回指纹图像数据
        {
            return FingerPic;
        }

        public int GetPicWidth()//返回指纹图像宽度
        {
            return FingerWidth;
        }
        public int GetPicHeight()//返回指纹图像高度
        {
            return FingerHeight;
        }
        #endregion

        #region 指纹仪操作函数
        /// <summary>
        /// 以下部分函数是指纹仪操作功能的入口函数
        /// 其他模块通过这部分函数对指纹仪进行操作
        /// </summary>
        /// <returns></returns>
        /// 
        public int GetDevID()//获取指纹仪ID
        {
            #region 构造取指纹仪ID的数据包
            //3A 01 00 40 00 04 7F 00 00 00 00 01

            byte[] a = new byte[12];
            a[0] = 0x3a;
            a[1] = 0x01;
            a[2] = 0x00;
            a[3] = 0x40;
            a[4] = 0x00;
            a[5] = 0x04;
            a[6] = 0x7F;
            a[7] = 0x00;
            a[8] = 0x00;
            a[9] = 0x00;
            a[10] = 0x00;
            a[11] = 0x01;
            #endregion
            WriteProtCmd(a);
            //修改指纹仪工作状态
            WorkingMode = 9;//工作状态为9
            State = 0;
            return 0;
        }
        public int GetDevcNum()//获取指纹仪编号
        {
            #region 构造取指纹仪编号的数据包
            //3A 01 00 80 00 00 BB 89 

            byte[] a = new byte[8];
            a[0] = 0x3a;
            a[1] = 0x01;
            a[2] = 0x00;
            a[3] = 0x80;
            a[4] = 0x00;
            a[5] = 0x00;
            a[6] = 0xBB;
            a[7] = 0x89;
            #endregion
            WriteProtCmd(a);
            //修改指纹仪工作状态
            WorkingMode = 11;//工作状态为9
            State = 0;
            return 0;
        }
        public int GetSecuClass()//获取指纹仪安全等级
        {
            #region 构造取指纹仪安全等级的数据包
            // 3A 01 00 10 00 00 2B 89 

            byte[] a = new byte[8];
            a[0] = 0x3a;
            a[1] = 0x01;
            a[2] = 0x00;
            a[3] = 0x10;
            a[4] = 0x00;
            a[5] = 0x00;
            a[6] = 0x2B;
            a[7] = 0x89;
            #endregion
            WriteProtCmd(a);
            //修改指纹仪工作状态
            WorkingMode = 10;//工作状态为10
            State = 0;
            return 0;
        }
        public int StopLastCmd()//终止上一次的命令
        {
            #region 构造中断命令的数据包
            //3a 00 00 00 00 00 3a 8b 中断正在进行的任务

            byte[] a = new byte[8];
            a[0] = 0x3a;
            a[1] = 0x00;
            a[2] = 0x00;
            a[3] = 0x00;
            a[4] = 0x00;
            a[5] = 0x00;
            a[6] = 0x3a;
            a[7] = 0x8b;
            #endregion
            WriteProtCmd(a);
            //修改指纹仪工作状态
            WorkingMode = 1;
            State = 0;
            return 0;
        }
        public int GetFingerNumber(int StartID, int EndID)//向指纹仪查询指纹仪存储的指纹数目
        {
            #region 构造查询指纹数目的数据包
            //发送3a 01 00 20 00 04 1f 00 00 00 63 1e
            byte[] a = new byte[12];
            a[0] = 0x3a;
            a[1] = 0x01;
            a[2] = 0x00;
            a[3] = 0x20;
            a[4] = 0x00;
            a[5] = 0x04;
            a[6] = 0x1f;
            //以上为可固定内容，后续4个字节需要通过输入的ID进行计算
            a[7] = (byte)(StartID / 256);
            a[8] = (byte)(StartID % 256);
            a[9] = (byte)(EndID / 256);
            a[10] = (byte)(EndID % 256);
            //需要重新计算SUM值
            a[11] = FingerSC.FingerSUM(a, a.Length);
            #endregion
            WriteProtCmd(a);
            //修改状态
            WorkingMode = 2;
            State = 0;

            FingerID1 = StartID;
            FingerID2 = EndID;

            return 0;

        }
        public int CollectFinger()//采集指纹图像
        {
            #region 构造查询指纹数目的数据包
            byte[] a = new byte[8];
            a[0] = 0x3a;
            a[1] = 0x02;
            a[2] = 0xaa;
            a[3] = 0x00;
            a[4] = 0x00;
            a[5] = 0x00;
            a[6] = 0x92;
            a[7] = 0x87;
            #endregion
            WriteProtCmd(a);

            FingerDeviceCallback(new FingerDeviceCallbackValue
            {
                CallbackType = Enum_FingerDeviceCallbackType.FingerprintImage_Entrying,
                FingerPrintID = 0,
                MessgeaInfo = "获取指纹图像数据中",
                Para1 = null,
            });

            //修改状态
            WorkingMode = 3;
            State = 0;
            return 0;
        }
        public int RegNewFinger(int StartID)//指纹注册；指定注册的位置
        {
            #region 构造指纹注册命令的数据包
            //3a 03 a6 a0 00 04 3b 00 00 00 63 da

            byte[] a = new byte[12];
            a[0] = 0x3a;
            a[1] = 0x03;
            a[2] = 0xa6;
            a[3] = 0xa0;
            a[4] = 0x00;
            a[5] = 0x04;
            a[6] = 0x3b;
            //以上为可固定内容，后续4个字节需要通过输入的ID进行计算
            a[7] = (byte)(StartID / 256);
            a[8] = (byte)(StartID % 256);
            a[9] = (byte)(StartID / 256);
            a[10] = (byte)(StartID % 256);
            //需要重新计算SUM值
            a[11] = FingerSC.FingerSUM(a, a.Length);
            #endregion
            WriteProtCmd(a);
            //修改状态
            WorkingMode = 4;
            State = 0;
            //保存起止ID编号
            FingerID1 = StartID;
            FingerEventArgs fre = new FingerEventArgs("请按下指纹", WorkingMode, State, 0, FingerID1, null);
            this.Alarm(this, fre);
            FingerDeviceCallback(new FingerDeviceCallbackValue
            {
                CallbackType = Enum_FingerDeviceCallbackType.Register_FirstEntrying,
                FingerPrintID = StartID,
                MessgeaInfo = "请按下指纹",
                Para1 = null,
            });
            return 0;
        }

        public int RegNewFinger(int StartID, int EndID)//指纹注册；指定注册的范围
        {
            #region 构造指纹注册命令的数据包
            //3a 03 a6 a0 00 04 3b 00 00 00 63 da

            byte[] a = new byte[12];
            a[0] = 0x3a;
            a[1] = 0x03;
            a[2] = 0xa6;
            a[3] = 0xa0;
            a[4] = 0x00;
            a[5] = 0x04;
            a[6] = 0x3b;
            //以上为可固定内容，后续4个字节需要通过输入的ID进行计算
            a[7] = (byte)(StartID / 256);
            a[8] = (byte)(StartID % 256);
            a[9] = (byte)(EndID / 256);
            a[10] = (byte)(EndID % 256);
            //需要重新计算SUM值
            a[11] = FingerSC.FingerSUM(a, a.Length);
            #endregion
            WriteProtCmd(a);
            //修改状态
            WorkingMode = 4;
            State = 0;
            //保存起止ID编号
            FingerID1 = StartID;
            FingerID2 = EndID;
            return 0;
        }
        public int MatchFinger(int StartID, int EndID)//匹配指纹
        {
            #region 构造匹配指纹的数据包
            byte[] a = new byte[12];
            //包头
            a[0] = 0x3a;
            //指令
            a[1] = 0x04;
            //功能参数
            a[2] = 0xa6;
            a[3] = 0x80;
            //包长度
            a[4] = 0x00;
            a[5] = 0x04;
            //异或校验
            a[6] = FingerXOR(a);
            //起始指纹ID
            a[7] = (byte)(StartID / 256);
            a[8] = (byte)(StartID % 256);
            //结束指纹ID
            a[9] = (byte)(EndID / 256);
            a[10] = (byte)(EndID % 256);
            //校验和
            a[11] = FingerSUM(a, a.Length);
            #endregion 构造删除指纹的命令包
            WriteProtCmd(a);
            WorkingMode = 5;
            State = 0;
            FingerID1 = StartID;
            FingerID2 = EndID;

            FingerDeviceCallback(new FingerDeviceCallbackValue
            {
                CallbackType = Enum_FingerDeviceCallbackType.FingerprintVerification_Entrying,
                FingerPrintID = 0,
                MessgeaInfo = "正在验证指纹",
                Para1 = null,
            });

            return 0;
        }
        public int DeleterFinger(int StartID, int EndID)//删除指纹
        {
            #region 构造删除指纹的数据包
            byte[] a = new byte[12];
            //包头
            a[0] = 0x3a;
            //指令
            a[1] = 0x05;
            //功能参数
            a[2] = 0xe0;
            a[3] = 0x00;
            //包长度
            a[4] = 0x00;
            a[5] = 0x04;
            //异或校验
            a[6] = FingerXOR(a);
            //删除的起始指纹ID
            a[7] = (byte)(StartID / 256);
            a[8] = (byte)(StartID % 256);
            //删除的结束指纹ID
            a[9] = (byte)(EndID / 256);
            a[10] = (byte)(EndID % 256);
            //校验和
            a[11] = FingerSUM(a, a.Length);
            #endregion 构造删除指纹的命令包
            WriteProtCmd(a);
            WorkingMode = 6;
            State = 0;
            FingerID1 = StartID;
            FingerID2 = EndID;
            return 0;
        }
        public int GetFingerModel(int FingerID, int ModelID)//获取模板
        {
            #region 构造获取指纹模板的数据包
            //3a 06 00 c0 00 04 f8 00 00 00 00 03
            byte[] a = new byte[12];
            //包头
            a[0] = 0x3a;
            //指令
            a[1] = 0x06;
            //功能参数
            a[2] = 0x00;
            a[3] = 0xc0;
            //包长度
            a[4] = 0x00;
            a[5] = 0x04;
            //异或校验
            a[6] = FingerXOR(a);
            //删除的起始指纹ID
            a[7] = (byte)(FingerID / 256);
            a[8] = (byte)(FingerID % 256);
            //删除的结束指纹ID
            a[9] = (byte)(ModelID % 256);
            a[10] = 0x00;//开始都是第一个数据包
            //校验和
            a[11] = FingerSUM(a, a.Length);
            #endregion 构造获取指纹模板的数据包
            WriteProtCmd(a);
            //修改状态
            WorkingMode = 7;
            State = 0;
            //记录拷贝的指纹ID和模板ID
            FingerID1 = FingerID;
            FingerModelID1 = ModelID;
            return 0;
        }

        /// <summary>
        /// 下发指纹模板
        /// </summary>
        /// <param name="FingerID">指纹ID</param>
        /// <param name="ModelID">模板ID</param>
        /// <param name="sFingerPrtTmp1">模板1数据</param>
        /// <param name="sFingerPrtTmp2">模板2数据</param>
        /// <returns></returns>
        public int DownLoadFinger(int FingerID, int ModelID, string sFingerPrtTmp1, string sFingerPrtTmp2)//从上位机下载指纹到指纹仪
        {
            #region 构造下载指纹的数据包
            //3a 06 00 30 00 04 08 00 00 00 00 83
            byte[] a = new byte[12];
            //包头
            a[0] = 0x3a;
            //指令
            a[1] = 0x06;
            //功能参数
            a[2] = 0x00;
            a[3] = 0x30;
            //包长度
            a[4] = 0x00;
            a[5] = 0x04;
            //异或校验
            a[6] = FingerXOR(a);
            //指纹ID
            a[7] = (byte)(FingerID / 256);
            a[8] = (byte)(FingerID % 256);
            //模板ID
            a[9] = (byte)(ModelID % 256);
            a[10] = 0x00;//开始都是第一个数据包
            //校验和
            a[11] = FingerSUM(a, a.Length);
            #endregion 构造下发指纹的命令包
            WriteProtCmd(a);
            //修改状态
            WorkingMode = 8;
            State = 0;
            //记录拷贝的指纹ID和模板ID
            FingerID1 = FingerID;
            FingerModelID1 = ModelID;
            FingerPrtTmp1 = strToHexByte(sFingerPrtTmp1);
            FingerPrtTmp2 = strToHexByte(sFingerPrtTmp2);

            EventArgs e = new EventArgs();

            return 0;
        }

        public int DownLoadFinger(FingerModelInfo modelInfo)//从上位机下载指纹到指纹仪
        {
            #region 构造下载指纹的数据包
            //3a 06 00 30 00 04 08 00 00 00 00 83
            byte[] a = new byte[12];
            //包头
            a[0] = 0x3a;
            //指令
            a[1] = 0x06;
            //功能参数
            a[2] = 0x00;
            a[3] = 0x30;
            //包长度
            a[4] = 0x00;
            a[5] = 0x04;
            //异或校验
            a[6] = FingerXOR(a);
            //指纹ID
            a[7] = (byte)(modelInfo.FingerPrintID / 256);
            a[8] = (byte)(modelInfo.FingerPrintID % 256);
            //模板ID
            a[9] = (byte)(modelInfo.FingerDeviceModelID % 256);
            a[10] = 0x00;//开始都是第一个数据包
            //校验和
            a[11] = FingerSUM(a, a.Length);
            #endregion 构造下发指纹的命令包
            WriteProtCmd(a);
            //修改状态
            WorkingMode = 8;
            State = 0;
            //记录拷贝的指纹ID和模板ID
            FingerID1 = modelInfo.FingerPrintID;
            FingerModelID1 = modelInfo.FingerDeviceModelID;
            for (int i = 0; i < 256; i++)
            {
                FingerPrtTmp1[i] = modelInfo.FigerModelContent[i];
                FingerPrtTmp2[i] = modelInfo.FigerModelContent[(256 + i)];
            }

            EventArgs e = new EventArgs();
            
            return 0;
        }



        #endregion

        #region 基础函数
        /// <summary>
        /// 
        /// 异或校验
        /// </summary>
        /// <param name="XORData">校验数据</param>
        /// <returns></returns>
        private static byte FingerXOR(byte[] XORData, int XORLenth = 6)
        {
            byte xor = 0x0;
            for (int i = 0; i < XORLenth; i++)
            {
                xor ^= XORData[i];
            }
            return xor;
        }

        /// <summary>
        /// 校验和
        /// </summary>
        /// <param name="SUMData">校验数据</param>
        /// <param name="pack_len">拓展域长度</param>
        /// <returns></returns>
        private static byte FingerSUM(byte[] SUMData, int pack_len)
        {
            byte sum = 0x0;
            int n = pack_len - 8;
            for (int i = 0; i < (7 + n); i++)
            {
                sum += SUMData[i];
            }

            sum = Convert.ToByte((~sum) & 0xff);
            return sum;
        }

        public string byteToHexStr(byte[] bytes)//第二次修改新增，用于将比特数组转换成字符串 by szy
        {
            string str = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    str += bytes[i].ToString("X2");
                }
            }
            return str;
        }
        public static byte[] strToHexByte(string hexString)//第二次修改新增，用于将字符串转换成Byte数组，by szy
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        private Bitmap RawToBitmap(byte[] RawSource, int width, int height)
        {
            Bitmap bm = new Bitmap(width, height);
            byte input;
            //注意：指纹仪上传的图像数据是Raw格式的，需要转换为BMP格式的图像才能在pictureBox中显示。
            //Raw数据是按行存储的。
            //本函数可以写入到FingerSC中。
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    input = RawSource[j * width + i];
                    bm.SetPixel(i, j, Color.FromArgb(input, input, input));
                }
            }
            return bm;
        }
        #endregion

        #region 最重要的数据接收事件处理函数。
        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Byte[] receivedData;//从串口接收的数据保存在该数组中
            string strReturn = "错误信息：";//数据相关信息，用于通知上一层
            //先接收数据再进行后续的处理
            #region 数据接收
            Thread.Sleep(50);//本进程延迟50毫秒，等待串口所有数据传送完毕。
                             //指纹仪一次传送数据最大为280字节在115200波特率下大约需要20ms，
                             //当事件发生时立即取数据，有可能数据没有取完造成错误。

            receivedData = new Byte[FSCCom.BytesToRead];        //创建接收字节数组
            if (receivedData.Length <= 0)
            {
                return;
            }
            FSCCom.Read(receivedData, 0, receivedData.Length);         //读取数据
            #endregion
            //应该在这里实现错误码的校验过程，即产品说明书中第三页的表格
            #region 错误校验
            int error = receivedData[2] / 16;//获取应答信息中的最高4位
            if (error == 8)//如果该值为8说明发生了错误或异常
            {
                int des = receivedData[2] % 16;//第3字节的低四位
                des = des * 16 * 16 + receivedData[3];//与第4字节拼接成为异常的错误代码
                switch (des)//针对不同错误代码，进行不同的处理，目前主要是返回错误信息
                {
                    case 0xF01:
                        strReturn += "XOR校验错误。";
                        break;
                    case 0xF02:
                        strReturn += "SUM校验错误。";
                        break;
                    case 0xF03:
                        strReturn += "指令错误。";
                        break;
                    case 0xF04:
                        strReturn += "参数错误。";
                        break;
                    case 0xF05:
                        strReturn += "通信超时。";
                        break;
                    case 0xF06:
                        strReturn += "无系统文件。";
                        break;
                    case 0xF07:
                        strReturn += "系统错误。";
                        break;
                    case 0xF08:
                        strReturn += "扩展域-参数错误。";
                        break;
                    case 0x101:
                        strReturn += "传感器初始化失败。";
                        break;
                    case 0x102:
                        strReturn += "传感器校正失败。";
                        break;
                    case 0x201:
                        strReturn += "手指检测超时。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.Finger_Detection_Timeout,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x202:
                        strReturn += "图像采集失败。";
                        break;
                    case 0x203:
                        strReturn += "手指检测超时。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.Finger_Detection_Timeout,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x301:
                        strReturn += "指纹注册满。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.Register_EntryFail,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x302:
                        strReturn += "与临时模板1匹配失败。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.FingerprintVerification_Fail,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x303:
                        strReturn += "与临时模板2匹配失败。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.FingerprintVerification_Fail,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x304:
                        strReturn += "指纹以注册。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.Register_EntryFail,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x401:
                        strReturn += "无注册指纹。";
                        break;
                    case 0x402:
                        strReturn += "匹配失败。";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.FingerprintVerification_Fail,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                    case 0x403:
                        strReturn += "更新模板失败。";
                        break;
                    case 0x501:
                        strReturn += "删除指定的指纹模板失败。";
                        break;
                    case 0x601:
                        strReturn += "指纹模板无效。";
                        break;
                    default:
                        strReturn += $"未识别的错误代码：{des}";
                        FingerDeviceCallback(new FingerDeviceCallbackValue
                        {
                            CallbackType = Enum_FingerDeviceCallbackType.Undefined,
                            FingerPrintID = FingerID1,
                            MessgeaInfo = strReturn,
                            Para1 = null,
                        });
                        break;
                }
                //用事件通知感兴趣的对象
                strReturn += byteToHexStr(receivedData);
                FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, -1, -1, receivedData);
                this.Alarm(this, fre);
                
                //失败后，各种状态归零
                WorkingMode = 0;
                State = 0;
                return;//直接结束，不进行后续处理
            }
            #endregion

            //由于与指纹仪进行交互，不同的工作状态有不同的交互需要。
            //由于错误已经处理过了，可以认为34字节都为0，即正常的响应信息

            switch (WorkingMode)//0无事等待指纹仪消息；1中断指令；2查询指纹数；3采集图像；4注册指纹；5匹配指纹；6删除指纹；7模板传输。
            {
                case 0://以前没有发送过指令，等待指纹仪的主动消息。目前好像没有相关支持。
                    break;
                case 1://1中断指令
                    if (receivedData[1] == 0x00) //中断目前正在做的事
                    {
                        //改变命令处理的状态
                        State = 1;//收到回复正在处理
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            strReturn = "当前指令模式：" + WorkingMode.ToString() + "。中断成功。";
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, 0, receivedData);
                            this.Alarm(this, fre);

                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道前一指令已经成功中断
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;
                            break;
                        }
                    }
                    break;
                case 2://2查询指纹数；
                    if (receivedData[1] == 0x01) //返回指纹数
                    {
                        //改变命令处理的状态
                        State = 1;//收到回复正在处理
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            FingerNum = receivedData[7] * 256 + receivedData[8];
                            strReturn = "指纹ID数：" + FingerNum.ToString();
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerNum, receivedData);
                            this.Alarm(this, fre);

                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道指纹数已经返回
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;
                            break;
                        }
                    }
                    break;
                case 3://3采集图像；
                    //采集图像有多次交互过程，需要多个状态标明进度这个状态由State保存记录
                    //update by xxd 2018/12/15原来对采集图像有误解，以为就是模板数据
                    //实际上是图像数据，需要传输接近100k的数据
                    switch (State)
                    {
                        case 0://发出命令，等待指纹仪回应
                            if (receivedData[1] == 0x02) //返回采集图像应答，可获得图像的高度和宽度
                            {
                                //改变命令处理的状态
                                State = 1;//收到回复正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    FingerWidth = receivedData[7] * 256 + receivedData[8];
                                    strReturn = "指纹宽度：" + FingerWidth.ToString() + ";";
                                    FingerHeight = receivedData[9] * 256 + receivedData[10];
                                    strReturn += "指纹高度：" + FingerHeight.ToString() + ";";

                                    //获得指纹图像参数后，可以计算出指纹图像的大小
                                    //一个像素8位，所以一个像素就一个字节
                                    //传输以256为单位传送，因此size需要扩展一些。
                                    FingerPicSize = ((FingerWidth * FingerHeight) / 256 + 1) * 256;
                                    FingerPic = new byte[FingerPicSize];//这里直接创建图像对象，不知道有没有问题。因为多次采集图像，可能会造成内存泄漏。
                                    isPicValid = false;//现在图像数据无效，要等到数据接收完毕
                                    PicPackNum = 0;//包接收计数器。


                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerPicSize, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    //构造数据包，下发到指纹仪要求下一个数据回应
                                    #region 构造查询图像第0包数据的指令
                                    //发送3a 06 80 00 00 04 b8 00 00 01 00 82
                                    byte[] a = new byte[12];
                                    a[0] = 0x3a;
                                    a[1] = 0x06;
                                    a[2] = 0x80;
                                    a[3] = 0x00;
                                    a[4] = 0x00;
                                    a[5] = 0x04;
                                    a[6] = 0xb8;
                                    a[7] = 0x00;
                                    a[8] = 0x00;
                                    a[9] = 0x01;
                                    a[10] = 0x00;
                                    a[11] = 0x82;
                                    #endregion
                                    WriteProtCmd(a);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 2;//工作状态向前进，等待串口数据返回
                                    break;
                                }
                            }
                            break;
                        case 2://等待串口数据返回,将接受后续所有的图像数据
                            if (receivedData[1] == 0x06) //返回采集图像应答
                            {
                                //改变命令处理的状态
                                State = 3;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    if (receivedData.Length < 278)//接收的数据量不够
                                    {
                                        //报错
                                        strReturn = "指纹第一个数据包数据量不够;";
                                        //构造事件的参数，触发事件
                                        FingerEventArgs fre1 = new FingerEventArgs(strReturn, WorkingMode, State, -1, 0, null);
                                        this.Alarm(this, fre1);

                                        //this.Alarm(strReturn, new EventArgs());//触发事件
                                        return;
                                    }

                                    strReturn = "指纹第" + PicPackNum.ToString() + "个数据包,已复制到临时变量中;";
                                    //在这里处理指纹数据包，即把获得的数据存放到指纹图像的成员变量中
                                    //注意计算起止位置
                                    Array.Copy(receivedData, 10, FingerPic, PicPackNum * 256, 256);//每次256因此起始位置是PicPackNum * 256
                                    PicPackNum++;//准备接收下一个包
                                    if (PicPackNum * 256 >= FingerPic.Length)//如果数据已经接收完毕，那么工作状态就要发生改变
                                    {
                                        WorkingMode = 0;//工作模式变回0
                                        State = 0;//状态变为0
                                        isPicValid = true;//图像数据有效，可供访问


                                        FingerDeviceCallback(new FingerDeviceCallbackValue
                                        {
                                            CallbackType = Enum_FingerDeviceCallbackType.FingerprintImage_Success,
                                            FingerPrintID = 0,
                                            MessgeaInfo = "获取指纹图像数据完成",
                                            Para1 = null,
                                        });


                                        break;
                                    }
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, PicPackNum, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    //向指纹仪下发
                                    #region 构造查询图像第PicPackNum包数据的指令
                                    //发送3a 06 80 00 00 04 b8 00 01 01 00 **
                                    byte[] a = new byte[12];
                                    a[0] = 0x3a;
                                    a[1] = 0x06;
                                    a[2] = 0x80;
                                    a[3] = 0x00;
                                    a[4] = 0x00;
                                    a[5] = 0x04;
                                    a[6] = 0xb8;
                                    a[7] = (byte)(PicPackNum / 256);//这里是PicPackNum的高8位
                                    a[8] = (byte)(PicPackNum % 256);//这里是PicPackNum的低8位
                                    a[9] = 0x01;
                                    a[10] = 0x00;
                                    a[11] = FingerSUM(a, 11);
                                    #endregion
                                    WriteProtCmd(a);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 2;//工作状态不变，一直用状态2接收图像数据
                                    break;
                                }
                            }
                            break;
                        case 4://等待串口数据返回,获得图像的第0个数据包
                            if (receivedData[1] == 0x06) //返回采集图像应答
                            {
                                //改变命令处理的状态
                                State = 5;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    if (receivedData.Length < 278)//接收的数据量不够
                                    {
                                        //报错
                                        strReturn = "指纹第二个数据包数据量不够";
                                        //构造事件的参数，触发事件
                                        FingerEventArgs fre1 = new FingerEventArgs(strReturn, WorkingMode, State, -1, PicPackNum, null);
                                        this.Alarm(this, fre1);

                                        //this.Alarm(strReturn, new EventArgs());//触发事件
                                        return;
                                    }
                                    strReturn = "指纹第二个数据包,已复制到临时变量中";
                                    //在这里处理指纹数据包，即把获得的指纹数据存放到成员变量中
                                    Array.Copy(receivedData, 10, FingerPrtTmp2, 0, 256);
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, PicPackNum, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    strFingerPrtTmp1 = byteToHexStr(FingerPrtTmp1);
                                    strFingerPrtTmp2 = byteToHexStr(FingerPrtTmp2);
                                    this.FingerPrtTmp(this, strFingerPrtTmp1, strFingerPrtTmp2, new EventArgs());//触发事件
                                    //操作结束，各状态回复到正常状态
                                    WorkingMode = 0;
                                    State = 0;
                                    break;
                                }
                            }
                            break;

                        default:
                            break;
                    }
                    break;
                case 4://4注册指纹（基本完成）
                    switch (State)
                    {
                        case 0:
                            if (receivedData[1] == 0x03) //注册指纹
                            {
                                //改变命令处理的状态
                                State = 1;//收到回复正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.Register_FirstEntryend,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = "请放开手指",
                                        Para1 = null,
                                    });
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);
                                    Thread.Sleep(1500);
                                    
                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    //构造数据包，下发到指纹仪要求下一个数据回应
                                    #region 构造上传指纹模板图像第1包数据的指令
                                    //发送3a 03 a6 60 00 04 fb 00 00 00 63 5a
                                    byte[] a = new byte[12];
                                    a[0] = 0x3a;
                                    a[1] = 0x03;
                                    a[2] = 0xa6;
                                    a[3] = 0x60;
                                    a[4] = 0x00;
                                    a[5] = 0x04;
                                    a[6] = 0xfb;
                                    //需要通过指纹ID计算
                                    a[7] = (byte)(FingerID1 / 256);
                                    a[8] = (byte)(FingerID1 % 256);
                                    a[9] = (byte)(FingerID1 / 256);
                                    a[10] = (byte)(FingerID1 % 256);
                                    //通过函数求和
                                    a[11] = FingerSC.FingerSUM(a, a.Length);
                                    #endregion
                                    WriteProtCmd(a);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 2;//工作状态向前进
                                              //构造事件的参数，触发事件

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.Register_SencondEntrying,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = "请第二次按下手指",
                                        Para1 = null,
                                    });
                                    break;
                                }
                            }
                            break;
                        case 2://第二次注册返回的消息
                            if (receivedData[1] == 0x03) //注册指纹
                            {
                                //改变命令处理的状态
                                State = 3;//收到回复正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.Register_SencondEntryend,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = "请放开手指",
                                        Para1 = null,
                                    });
                                    Thread.Sleep(1500);
                                   
                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    //构造数据包，下发到指纹仪要求下一个数据回应
                                    #region 构造注册指纹第3次的指令
                                    //发送3a 03 a6 1c 00 04 87 00 00 00 63 12
                                    byte[] a = new byte[12];
                                    a[0] = 0x3a;
                                    a[1] = 0x03;
                                    a[2] = 0xa6;
                                    a[3] = 0x1c;
                                    a[4] = 0x00;
                                    a[5] = 0x04;
                                    a[6] = 0x87;
                                    //ID范围
                                    a[7] = (byte)(FingerID1 / 256);
                                    a[8] = (byte)(FingerID1 % 256);
                                    a[9] = (byte)(FingerID1 / 256);
                                    a[10] = (byte)(FingerID1 % 256);
                                    //重新计算综合
                                    a[11] = FingerSUM(a, a.Length);
                                    #endregion
                                    WriteProtCmd(a);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 4;//工作状态向前进，等待串口数据返回

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.Register_ThirdEntrying,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = "请第三次按下手指",
                                        Para1 = null,
                                    });
                                    break;
                                }
                            }
                            break;
                        case 4://第三次注册的返回消息
                            if (receivedData[1] == 0x03) //注册指纹
                            {
                                //改变命令处理的状态
                                State = 5;//收到回复正在处理

                                //注册完成，状态归零
                                WorkingMode = 0;//
                                State = 0;//
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    FingerID1 = receivedData[7] * 256 + receivedData[8];
                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.Register_EntrySuccess,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = "指纹注册成功",
                                        Para1 = null,
                                    });

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    break;
                                }
                            }
                            break;
                    }
                    break;
                case 5://5匹配指纹
                    if (receivedData[1] == 0x04) //判断应答信息是否正确
                    {
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            ///匹配成功的ID。
                            FingerID1 = receivedData[7] * 256 + receivedData[8];
                            strReturn = "匹配成功。ID为:" + FingerID1.ToString();
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                            this.Alarm(this, fre);
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;
                            FingerDeviceCallback(new FingerDeviceCallbackValue
                            {
                                CallbackType = Enum_FingerDeviceCallbackType.FingerprintVerification_Success,
                                FingerPrintID = FingerID1,
                                MessgeaInfo = "指纹匹配成功",
                                Para1 = null,
                            });
                            break;
                        }
                        else//匹配失败；这部分内容可能用不上，因为失败的信息在前面就被处理了。
                        {
                            strReturn = "匹配失败";
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, -1, -1, receivedData);
                            this.Alarm(this, fre);
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;

                            FingerDeviceCallback(new FingerDeviceCallbackValue
                            {
                                CallbackType = Enum_FingerDeviceCallbackType.FingerprintVerification_Fail,
                                FingerPrintID = FingerID1,
                                MessgeaInfo = "指纹匹配失败",
                                Para1 = null,
                            });
                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道指纹匹配成功
                            break;
                        }
                    }
                    break;
                case 6://6删除指纹
                    if (receivedData[1] == 0x05) //判断应答信息是否正确
                    {
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            ///这里加入删除成功的处理代码。
                            strReturn = "删除成功";
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, receivedData);
                            this.Alarm(this, fre);

                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道指纹已经删除
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;

                            break;
                        }
                    }

                    break;
                case 7://7模板传输
                    switch (State)
                    {
                        case 0://发出命令，等待指纹仪回应
                            if (receivedData[1] == 0x06) //返回采集图像应答
                            {
                                //改变命令处理的状态
                                State = 1;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    if (receivedData.Length < 278)//接收的数据量不够
                                    {
                                        //报错
                                        strReturn = "指纹第1个数据包数据量不够";
                                        //构造事件的参数，触发事件
                                        FingerEventArgs fre1 = new FingerEventArgs(strReturn, WorkingMode, State, -1, -1, null);
                                        this.Alarm(this, fre1);

                                        //this.Alarm(strReturn, new EventArgs());//触发事件
                                        return;
                                    }

                                    Array.Copy(receivedData, 10, FingerPrtTmp1, 0, 256);
                                    strReturn = "指纹第1个数据包,已复制到临时变量中";
                                    //在这里处理指纹数据包，即把获得的指纹数据存放到成员变量中
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件

                                    #region 构造上传指纹模板图像第2包数据的指令
                                    //发送3a 06 00 c0 00 04 f8 00 00 00 01 03
                                    byte[] a = new byte[12];
                                    a[0] = 0x3a;
                                    a[1] = 0x06;
                                    a[2] = 0x00;
                                    a[3] = 0xc0;
                                    a[4] = 0x00;
                                    a[5] = 0x04;
                                    a[6] = 0xf8;
                                    //需要通过指纹ID计算
                                    a[7] = (byte)(FingerID1 / 256);
                                    a[8] = (byte)(FingerID1 % 256);
                                    //需要通过模板ID计算
                                    a[9] = (byte)(FingerModelID1 % 256);
                                    //区域号应该为1
                                    a[10] = 0x01;
                                    //通过函数求和
                                    a[11] = FingerSC.FingerSUM(a, a.Length);
                                    #endregion
                                    WriteProtCmd(a);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 2;//工作状态向前进
                                    break;
                                }
                            }
                            break;
                        case 2://等待串口数据返回,获得图像的第2个数据包
                            if (receivedData[1] == 0x06) //返回采集图像应答
                            {
                                //改变命令处理的状态
                                State = 5;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    if (receivedData.Length < 278)//接收的数据量不够
                                    {
                                        //报错
                                        strReturn = "指纹第2个数据包数据量不够";
                                        //构造事件的参数，触发事件
                                        FingerEventArgs fre1 = new FingerEventArgs(strReturn, WorkingMode, State, -1, -1, receivedData);
                                        this.Alarm(this, fre1);

                                        //this.Alarm(strReturn, new EventArgs());//触发事件
                                        return;
                                    }

                                    strReturn = "指纹第2个数据包,已复制到临时变量中";
                                    //在这里处理指纹数据包，即把获得的指纹数据存放到成员变量中
                                    Array.Copy(receivedData, 10, FingerPrtTmp2, 0, 256);
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    strFingerPrtTmp1 = byteToHexStr(FingerPrtTmp1);
                                    strFingerPrtTmp2 = byteToHexStr(FingerPrtTmp2);
                                    //this.FingerPrtTmp(this, strFingerPrtTmp1, strFingerPrtTmp2, new EventArgs());//触发事件

                                    //操作结束，各状态回复到正常状态
                                    WorkingMode = 0;
                                    State = 0;//工作状态向前进
                                    FingerModelInfo modelInfo = new FingerModelInfo
                                    {
                                        FingerDeviceGUID = StrGUID,
                                        FingerPrintID = FingerID1,
                                        FingerDeviceModelID = FingerModelID1,
                                        FigerModelContent = Method.MergerContent(FingerPrtTmp1, FingerPrtTmp2)
                                    };
                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.RequestModel_Success,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = "请求指纹模板成功",
                                        Para1 = modelInfo,
                                    });
                                };

                                break;
                            }
                            break;

                        default:
                            break;
                    }
                    break;
                case 8://8下发模板
                    switch (State)
                    {
                        case 0://发出命令，等待指纹仪回应
                            if (receivedData[1] == 0x06) //返回下发指纹数据的应答
                            {
                                //改变命令处理的状态
                                State = 1;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    strReturn = "指纹仪应答，已准备好接受指纹第1号数据包";
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    WriteProtCmd(FingerPrtTmp1);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 4;//工作状态向前进

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.DownloadModel_RequestModelData1,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = $"正在下发{FingerID1}的第{FingerModelID1 + 1}个指纹模板的前256字节",
                                        Para1 = null,
                                    });

                                    break;
                                }
                            }
                            break;
                        case 2://等待串口数据返回,下发图像的第2个数据包
                            if (receivedData[1] == 0x06) //返回下发指纹数据的应答
                            {
                                //改变命令处理的状态
                                State = 3;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    strReturn = "指纹仪应答，已准备好接受指纹第2号数据包";
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    WriteProtCmd(FingerPrtTmp2);
                                    //WorkingMode = 0;//注意这时workingmode不能变
                                    State = 6;//工作状态向前进

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.DownloadModel_DownModelData2,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = $"正在下发{FingerID1}的第{FingerModelID1 + 1}个指纹模板的后256字节",
                                        Para1 = null,
                                    });

                                    break;
                                }
                            }
                            break;
                        case 4:
                            if (receivedData[1] == 0x06) //返回下发指纹数据的应答
                            {
                                //改变命令处理的状态
                                State = 5;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    strReturn = "指纹仪应答，第1号数据包已接受完毕。";
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);
                                    
                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    #region 构造下载指纹的数据包
                                    //3a 06 00 30 00 04 08 00 00 00 01 83
                                    byte[] a = new byte[12];
                                    a[0] = 0x3a;
                                    a[1] = 0x06;
                                    a[2] = 0x00;
                                    a[3] = 0x30;
                                    a[4] = 0x00;
                                    a[5] = 0x04;
                                    a[6] = FingerXOR(a);
                                    //起始指纹ID
                                    a[7] = (byte)(FingerID1 / 256);
                                    a[8] = (byte)(FingerID1 % 256);
                                    //模板ID
                                    a[9] = (byte)(FingerModelID1 % 256);
                                    a[10] = 0x01;//第二部分
                                    a[11] = FingerSUM(a, a.Length);//校验和
                                    #endregion 构造下发指纹的命令包
                                    WriteProtCmd(a);
                                    State = 2;//工作状态向前进

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.DownloadModel_RequestModelData1,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = $"下发{FingerID1}的第{FingerModelID1 + 1}个指纹模板的前256字节成功",
                                        Para1 = null,
                                    });
                                    break;
                                }
                            }
                            break;
                        case 6:
                            if (receivedData[1] == 0x06) //返回下发指纹数据的应答
                            {
                                //改变命令处理的状态
                                State = 1;//收到数据包正在处理
                                if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                                {
                                    strReturn = "指纹仪应答，第2号数据包接受完毕。指纹下发完毕。";
                                    //构造事件的参数，触发事件
                                    FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, null);
                                    this.Alarm(this, fre);

                                    //this.Alarm(strReturn, new EventArgs());//触发事件
                                    WorkingMode = 0;//注意这时workingmode不能变
                                    State = 0;//工作状态向前进
                                    FingerModelInfo modelInfo = new FingerModelInfo
                                    {
                                        FingerDeviceGUID = StrGUID,
                                        FingerPrintID = FingerID1,
                                        FingerDeviceModelID = FingerModelID1,
                                        FigerModelContent = Method.MergerContent(FingerPrtTmp1, FingerPrtTmp2)
                                    };

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.DownloadModel_RequestModelData2,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = $"下发{FingerID1}的第{FingerModelID1 + 1}个指纹模板的后256字节成功",
                                        Para1 = modelInfo,
                                    });

                                    FingerDeviceCallback(new FingerDeviceCallbackValue
                                    {
                                        CallbackType = Enum_FingerDeviceCallbackType.DonwloadModel_DownModelDataSuccess,
                                        FingerPrintID = FingerID1,
                                        MessgeaInfo = $"下发{modelInfo.FingerPrintID}的第{modelInfo.FingerDeviceModelID + 1}个指纹模板完成",
                                        Para1 = modelInfo,
                                    });
                                    


                                    break;
                                }
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case 9://9查询指纹仪ID；
                    if (receivedData[1] == 0x01) //返回指纹数
                    {
                        //改变命令处理的状态
                        State = 1;//收到回复正在处理。
                                  //指纹仪应答示例：5e0360151373036363033
                                  //3A 01 00 00 00 0C 37 5E 00 36 00 01 51 37 30 36 36 30 33 65
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            byte[] byTemp = new byte[12];

                            Array.Copy(receivedData, 7, byTemp, 0, 12);
                            GUID = byTemp;
                            string strTemp = this.byteToHexStr(byTemp);
                            strReturn = "指纹仪ID数：" + strTemp;
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, FingerID1, byTemp);
                            this.Alarm(this, fre);

                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道指纹数已经返回
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;
                            break;
                        }
                    }
                    break;
                case 10://10查询指纹仪安全等级；
                    if (receivedData[1] == 0x01) //对应的指令编码
                    {
                        //改变命令处理的状态
                        State = 1;//收到回复正在处理。
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            strReturn = "指纹仪安全等级：" + receivedData[7].ToString();
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, receivedData[7], null);
                            this.Alarm(this, fre);

                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道指纹数已经返回
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;
                            break;
                        }
                    }
                    break;
                case 11://11查询指纹仪编码；
                    if (receivedData[1] == 0x01) //对应的指令编码
                    {
                        //改变命令处理的状态
                        State = 1;//收到回复正在处理。
                        if (receivedData[2] == 0x00 && receivedData[3] == 0x00) //0000表示成功
                        {
                            byte[] byTemp = new byte[4];

                            Array.Copy(receivedData, 7, byTemp, 0, 4);
                            string strTemp = this.byteToHexStr(byTemp);
                            strReturn = "指纹仪ID数：" + strTemp;
                            //构造事件的参数，触发事件
                            FingerEventArgs fre = new FingerEventArgs(strReturn, WorkingMode, State, 0, 0, byTemp);
                            this.Alarm(this, fre);

                            //this.Alarm(strReturn, new EventArgs());//触发事件，让外界知道指纹数已经返回
                            //命令处理完毕，工作状态回复到初始状态
                            WorkingMode = 0;
                            State = 0;
                            break;
                        }
                    }
                    break;

                default:
                    break;
            }
            return;
        }

        #endregion

        /// <summary>
        /// 写入Com口命令
        /// </summary>
        /// <param name="bytsCmd"></param>
        public void WriteProtCmd(byte[] bytsCmd)
        {
            if (FSCCom.IsOpen)
            {
                FSCCom.Write(bytsCmd, 0, bytsCmd.Length);//发送数据包
            }
            else
            {
                FingerDeviceCallback(new FingerDeviceCallbackValue
                {
                    CallbackType = Enum_FingerDeviceCallbackType.PortInitException,
                    FingerPrintID = -1,
                    MessgeaInfo = "指纹仪COM口未打开",
                    Para1 = null,
                });
            }
        }
    }
}

